package com.example.banksystem.service;

import com.example.banksystem.DepositType;
import com.example.banksystem.dao.AccountRepository;
import com.example.banksystem.dao.TransactionRepository;
import com.example.banksystem.entity.Deposit;
import jakarta.transaction.Transaction;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 存款服务接口
 */
public interface DepositService {
    // 处理存款业务（核心逻辑）
    Deposit processDeposit(Deposit deposit) throws Exception;
    List<Transaction> getTransactions(String date, String type); // 新增：查询流水
    // 获取所有存款类型
    DepositType[] getAllDepositTypes();
}

/**
 * 存款服务实现类
 */
@Service
class DepositServiceImpl implements com.example.banksystem.DepositService {

    @Resource
    private AccountRepository accountRepository; // 账户DAO（需自行实现）
    @Resource
    private TransactionRepository transactionRepository; // 交易记录DAO（需自行实现）

    @Override
    public Deposit processDeposit(Deposit deposit) throws Exception {
        // 1. 验证参数
        validateDepositParams(deposit);

        // 2. 验证银行卡号存在性
        Account account = accountRepository.findByCardNumber(deposit.getCardNumber());
        if (account == null) {
            throw new Exception("银行卡号不存在");
        }

        // 3. 验证交易密码（假设密码存储在账户表）
        if (!account.getTransactionPwd().equals(deposit.getTransactionPwd())) {
            throw new Exception("交易密码错误");
        }

        // 4. 生成交易记录
        Transaction transaction = new Transaction();
        transaction.setType(deposit.getType());
        transaction.setTime(LocalDateTime.now());
        transaction.setTargetAccount(account.getAccountId()); // 存款目标为当前账户
        transaction.setAmount(deposit.getAmount());
        transaction.setRemark(deposit.getRemark());

        // 5. 处理定期存款特殊逻辑
        if ("定期存款".equals(deposit.getType())) {
            transaction.setIsFixed(true);
            transaction.setMaturityDate(deposit.getMaturityDate());
            transaction.setMaturityInterest(calculateInterest(deposit)); // 计算利息
        }

        // 6. 保存交易记录（数据库触发器会自动更新账户余额，见init-admin-schema.sql）
        transactionRepository.save(transaction);

        // 7. 封装返回结果
        deposit.setTransactionId(transaction.getTransactionId());
        deposit.setTime(transaction.getTime());
        return deposit;
    }

    @Override
    public DepositType[] getAllDepositTypes() {
        return DepositType.values();
    }

    // 验证存款参数合法性
    private void validateDepositParams(Deposit deposit) throws Exception {
        if (deposit.getCardNumber() == null || deposit.getCardNumber().length() != 19) {
            throw new Exception("请输入19位有效的银行卡号");
        }
        if (deposit.getAmount() == null || deposit.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new Exception("存款金额必须大于0");
        }
        if (deposit.getTransactionPwd() == null || deposit.getTransactionPwd().length() != 6) {
            throw new Exception("交易密码必须为6位数字");
        }
        // 定期存款需验证到期时间
        if ("定期存款".equals(deposit.getType()) && deposit.getMaturityDate() == null) {
            throw new Exception("定期存款需设置到期时间");
        }
    }
    @Override
    public List<Transaction> getTransactions(String date, String type) {
        // 1. 实际项目中应从数据库查询（这里模拟数据）
        List<Transaction> transactions = new ArrayList<>();

        // 2. 模拟数据（实际应根据date和type筛选）
        Transaction t1 = new Transaction();
        t1.setId(1);
        t1.setTime(LocalDateTime.of(2025, 10, 10, 10, 30));
        t1.setAmount(new BigDecimal("5000"));
        t1.setType("定期存款");
        t1.setDue(LocalDateTime.of(2026, 10, 10, 10, 30));
        t1.setInterest(new BigDecimal("300"));
        t1.setNote("一年期定期");
        transactions.add(t1);

        // 可添加更多模拟数据...

        return transactions;
    }
    // 计算定期存款利息（示例：年利率2%，按年计算）
    private BigDecimal calculateInterest(Deposit deposit) {
        long months = java.time.temporal.ChronoUnit.MONTHS.between(
                LocalDateTime.now(), deposit.getMaturityDate()
        );
        return deposit.getAmount().multiply(new BigDecimal("0.02"))
                .multiply(new BigDecimal(months)).divide(new BigDecimal(12), 2, BigDecimal.ROUND_HALF_UP);
    }
}

